using System;
using Fadd.Globalization;
#if TEST
using Xunit;
#endif

namespace Fadd.Validation
{
    /// <summary>
    /// Validates that a string property represents valid Hex value (Value should not either too large or too small for an Int64).
    /// </summary>
    public class ValidateHexAttribute : ValidateAttribute
    {
        private const string DefaultMessage = "'{0}' is not a valid Hex value.";

        /// <summary>
        /// Name of the language item for this validation.
        /// </summary>
        public const string Name = "Hex";

        /// <summary>
        /// Validate value
        /// </summary>
        /// <param name="context">Can be used to send a context object to the validation class. Useful if you provide your own validation classes which need to get information from your application. <seealso cref="BeforeValidationEventArgs"/></param>
        /// <param name="value">value to validate</param>
        /// <returns>
        /// true if value passed the validation; otherwise false.
        /// </returns>
        /// <exception cref="NotSupportedException">Thrown if the value supplied is not a <see cref="string"/></exception>
        public override bool Validate(object context, object value)
        {

            if (value is string)
            {
               long tempLong;
               return long.TryParse((value as string), System.Globalization.NumberStyles.HexNumber, null,out tempLong);
            }   

            throw new NotSupportedException(value.GetType() + " is not supported.");
        }

        /// <summary>
        /// Localize error if validation failed.
        /// </summary>
        /// <param name="fieldName">Localized field name.</param>
        /// <param name="validationLanguage">Language node with all validation translations.</param>
        /// <returns>
        /// A localized error message if the validation failed; otherwise null.
        /// </returns>
        /// <example>
        /// 	<code>
        /// attribute.Localize("FirstName", "'{0}' is required");
        /// // will return "'{0}' is required" if the validation failed, else null.
        /// </code>
        /// </example>
        public override string Format(string fieldName, ILanguageNode validationLanguage)
        {
            string format = validationLanguage == null ? DefaultMessage : validationLanguage[Name];
            return string.Format(format, fieldName);
        }

        /// <summary>
        /// Determines if the validation class support the specified type.
        /// </summary>
        /// <param name="type">Property/Value type.</param>
        /// <returns>true if the type is supported.</returns>
        /// <remarks>
        /// Used when validation objects are generated.
        /// </remarks>
        public override bool SupportsType(Type type)
        {
            return type == typeof(string);
        }

#if TEST
        [Fact]
        private static void Test()
        {
            ValidateHexAttribute attribute = new ValidateHexAttribute();
            Assert.True(attribute.Validate(null, "ABCDEF"));
            Assert.True(attribute.Validate(null, " ABCDEF"));
            Assert.True(attribute.Validate(null, "ABCDEF "));
            Assert.True(attribute.Validate(null, " ABCDEF "));
            Assert.True(attribute.Validate(null, " abcDEF "));
            Assert.True(attribute.Validate(null, " 09cdEF1 "));
            Assert.True(attribute.Validate(null, " ffffffffffffffff "));
            
            Assert.False(attribute.Validate(null, "ABCDEFG"));
            Assert.False(attribute.Validate(null, "ABCD-EF"));
            // ourof range Int64
            Assert.False(attribute.Validate(null, " fffffffffffffffff "));
            
            

        }
#endif

    }
}
